package com.muyu.api.entity;

import com.muyu.api.response.ResultResponse;
import lombok.Builder;
import lombok.Data;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName: ResponseEntity
 * @Author: Zirun.Xin
 * @Date: 2025/4/9 下午3:30
 * @Version: 1.0
 * @Description: HTTP响应实体（仿Spring设计，解耦框架依赖）
 */
@Data
@Builder
public class ResponseEntity<T> {

    /**
     * HTTP状态码（遵循RFC 7231规范）
     *
     * @see <a href="https://tools.ietf.org/html/rfc7231">RFC 7231</a>
     */
    private final int status;

    /**
     * 响应头信息（大小写不敏感的多值Map）
     */
    private final Map<String, String> headers;

    /**
     * 响应体内容（支持泛型数据承载）
     */
    private final T body;

    /*------------ 核心工厂方法 ------------*/

    /**
     * 创建成功响应（状态码200）
     *
     * @param body 响应数据
     * @param <T>  数据类型
     * @return 响应实体
     */
    public static <T> ResponseEntity<T> ok(T body) {
        return ResponseEntity.<T>builder()
                .status(200)
                .headers(Collections.emptyMap())
                .body(body)
                .build();
    }

    /**
     * 创建自定义状态码响应
     *
     * @param status HTTP状态码
     * @param body   响应数据
     * @param <T>    数据类型
     * @return 响应实体
     */
    public static <T> ResponseEntity<T> status(int status, T body) {
        return ResponseEntity.<T>builder()
                .status(status)
                .headers(Collections.emptyMap())
                .body(body)
                .build();
    }

    /**
     * 创建带Location头的201 Created响应
     *
     * @param body     响应数据
     * @param location 资源地址
     * @param <T>      数据类型
     * @return 响应实体
     */
    public static <T> ResponseEntity<T> created(T body, String location) {
        return ResponseEntity.<T>builder()
                .status(201)
                .headers(Collections.singletonMap("Location", location))
                .body(body)
                .build();
    }

    /*------------ 流畅接口方法 ------------*/

    /**
     * 添加响应头
     *
     * @param headerName  头名称
     * @param headerValue 头值
     * @return 当前实例（链式调用）
     */
    public ResponseEntity<T> withHeader(String headerName, String headerValue) {
        Map<String, String> newHeaders = new HashMap<>(this.headers);
        newHeaders.put(headerName, headerValue);
        return ResponseEntity.<T>builder()
                .status(this.status)
                .headers(newHeaders)
                .body(this.body)
                .build();
    }

    /**
     * 替换响应体
     *
     * @param newBody 新响应体
     * @param <U>     新数据类型
     * @return 新响应实体
     */
    public <U> ResponseEntity<U> withBody(U newBody) {
        return ResponseEntity.<U>builder()
                .status(this.status)
                .headers(this.headers)
                .body(newBody)
                .build();
    }

    /*------------ 与ResultResponse集成 ------------*/

    /**
     * 创建业务错误响应
     *
     * @param result 业务错误结果
     * @param <T>    数据类型
     * @return 响应实体
     */
    public static <T> ResponseEntity<ResultResponse<T>> error(ResultResponse<T> result) {
        return ResponseEntity.<ResultResponse<T>>builder()
                .status(result.getCode())
                .headers(Collections.emptyMap())
                .body(result)
                .build();
    }

    /**
     * 快速创建404响应
     *
     * @param message 错误信息
     * @return 响应实体
     */
    public static ResponseEntity<ResultResponse<Void>> notFound(String message) {
        return error(ResultResponse.fail(404, message));
    }

    /**
     * 文件下载响应构建
     *
     * @param fileData    文件字节数组
     * @param contentType MIME类型
     * @param fileName    下载文件名
     * @return 文件响应实体
     */
    public static ResponseEntity<byte[]> file(byte[] fileData, String contentType, String fileName) {
        // 创建不可修改的Header Map
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", contentType);
        headers.put("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        return ResponseEntity.<byte[]>builder()
                .status(200)
                .headers(Collections.unmodifiableMap(headers))
                .body(fileData)
                .build();
    }
}
